package com.ebo.storage.redis;

public class RedisStorageKey {
	
    /** 使用用户ID生成的key的长度 */
    private static final int key_base_len = 10;
    
    private static final byte strFlag = 64;
    
    private static final byte maxLen = 63;

	 /**
     * 根据用户ID生成表示key的数组
     * 
     * @param userId
     *            //转换成int进行操作
     * @param keyFlag
     * @return
     */
    public static byte[] getByteArray(long userId, short keyFlag) {
        if(keyFlag < 0) 
            throw new IllegalArgumentException("The key flag must over zero");

        int keyFlagLen = keyFlag >= 256 ? 1 : 0;
        byte[] bytes = new byte[keyFlagLen + key_base_len];
        bytes[0] = 4;
        bytes[1] = (byte) (userId & 0XFF);
        bytes[2] = (byte) ((userId >> 8) & 0XFF);
        bytes[3] = (byte) ((userId >> 16) & 0XFF);
        bytes[4] = (byte) ((userId >> 24) & 0XFF);
        bytes[5] = (byte) ((userId >> 32) & 0XFF);
        bytes[6] = (byte) ((userId >> 40) & 0XFF);
        bytes[7] = (byte) ((userId >> 48) & 0XFF);
        bytes[8] = (byte) ((userId >> 56) & 0XFF);
        bytes[9] = (byte) (keyFlag & 0XFF);
        if (keyFlagLen == 1) {
            bytes[10] = (byte) ((keyFlag >> 8) & 0XFF);
        }
        return bytes;
    }
    
    public static byte[] getByteArray(int araId, long roleId, short keyFlag) {
        if(keyFlag < 0) 
            throw new IllegalArgumentException("The key flag must over zero");
        
        int keyFlagLen = keyFlag >= 256 ? 1 : 0;
        byte[] bytes = new byte[keyFlagLen + key_base_len];
        
        int userId = (int) roleId;
        bytes[0] = 4;
        bytes[1] = (byte) (araId & 0XFF);
        bytes[2] = (byte) ((araId >> 8) & 0XFF);
        bytes[3] = (byte) ((araId >> 16) & 0XFF);
        bytes[4] = (byte) ((araId >> 24) & 0XFF);
        bytes[5] = (byte) ((userId >> 32) & 0XFF);
        bytes[6] = (byte) ((userId >> 40) & 0XFF);
        bytes[7] = (byte) ((userId >> 48) & 0XFF);
        bytes[8] = (byte) ((userId >> 56) & 0XFF);
        bytes[9] = (byte) (keyFlag & 0XFF);
        if (keyFlagLen == 1) {
            bytes[10] = (byte) ((keyFlag >> 8) & 0XFF);
        }
        return bytes;
    }
    
    
    /**
     * 根据平台ID生成表示key的byte数组
     * 
     * @param platformId
     *           
     * @param keyFlag
     * @return
     */
    public static byte[] getByteArray(String platformId, short keyFlag) {
        int len = platformId.length();
        if (len > 60)
            throw new IllegalArgumentException("The platformId is too long");

        int keyFlagLen = keyFlag >= 256 ? 2 : 1;

        byte[] bytes = new byte[len + 1 + keyFlagLen];
        bytes[0] = (byte) (len | strFlag);
        for (int i = 0; i < len; i++) {
            bytes[i + 1] = (byte) platformId.charAt(i);
        }
        bytes[len + 1] = (byte) (keyFlag & 0XFF);
        if (keyFlagLen == 2) {
            bytes[len + 2] = (byte) ((keyFlag >> 8) & 0XFF);
        }
        return bytes;
    }

    public static String getString(byte[] key) {
    	return decodeString(key, 1, key[0] & maxLen);
    }
    
    public static byte[] getByteArray(String platformId, int areaId, long roleId, long time, short keyFlag) {
    	long userId = roleId | (areaId * 1l << 32);
        byte[] userIdBytes = getByteArray(userId, keyFlag);
        int len1 = platformId.length();
        int len2 = userIdBytes.length;
        if (len1 > maxLen)
            throw new IllegalArgumentException("The platformId is too long");

        byte[] bytes = new byte[len1 + 1 + len2 + 4];
        bytes[0] = (byte) (len1 | strFlag);
        for (int i = 0; i < len1; i++) {
            bytes[i + 1] = (byte) platformId.charAt(i);
        }
        for (int i = 0; i < len2; i++) {
            bytes[len1 + i + 1] = userIdBytes[i];
        }
        bytes[len1 + len2 + 1] = (byte) (time & 0XFF);
        bytes[len1 + len2 + 2] = (byte) ((time >> 8) & 0XFF);
        bytes[len1 + len2 + 3] = (byte) ((time >> 16) & 0XFF);
        bytes[len1 + len2 + 4] = (byte) ((time >> 24) & 0XFF);
        return bytes;
    }
    
    public static byte[] getByteArray(long roleId, int param1, int param2, short keyFlag) {
        byte[] userIdBytes = getByteArray(roleId, keyFlag);
        int len1 = userIdBytes.length;

        byte[] bytes = new byte[len1 + 1 + 4 + 4];
        bytes[0] = (byte) (len1 | strFlag);
        for (int i = 0; i < len1; i++) {
            bytes[i + 1] = userIdBytes[i];
        }
        bytes[len1 + 1] = (byte) (param1 & 0XFF);
        bytes[len1 + 2] = (byte) ((param1 >> 8) & 0XFF);
        bytes[len1 + 3] = (byte) ((param1 >> 16) & 0XFF);
        bytes[len1 + 4] = (byte) ((param1 >> 24) & 0XFF);
        bytes[len1 + 4 + 1] = (byte) (param2 & 0XFF);
        bytes[len1 + 4 + 2] = (byte) ((param2 >> 8) & 0XFF);
        bytes[len1 + 4 + 3] = (byte) ((param2 >> 16) & 0XFF);
        bytes[len1 + 4 + 4] = (byte) ((param2 >> 24) & 0XFF);
        return bytes;
    }
    
    /**
     * 获取key中用来hash的int值 使用userId生成的返回userId
     * 使用platformId生成的返回platformId的hashCode
     * 
     * @param bytes
     * @return
     */
    public static int getHash(byte[] bytes) {
        int len = bytes[0];
        if ((len & strFlag) > 0) {
            return Math.abs(decodeString(bytes, 1, len & maxLen).hashCode());
        } else {
            return decodeInt(bytes);
        }
    }
    
    private static String decodeString(byte[] bytes, int spos, int len) {
        char[] chars = new char[len];
        int epos = len + spos;
        int index = 0;
        for (int i = spos; i < epos; i++) {
            chars[index++] = (char) bytes[i];
        }
        return new String(chars);
    }
    
    private static int decodeInt(byte[] bytes) {
        int value = 0;
        value |= (bytes[1] & 0xFF);
        value |= ((bytes[2] & 0xFF) << 8);
        value |= ((bytes[3] & 0xFF) << 16);
        value |= ((bytes[4] & 0xFF) << 24);
        return value;
    }
	
}
